#include <functional>
#include <vector>
#include <algorithm>
#include <iterator>
#include <iostream>
#include <cmath>
#include <cassert>

using namespace std::tr1::placeholders;
using namespace std::tr1;

using std::ostream_iterator;
using std::vector;
using std::cout;
using std::endl;
using std::multiplies;
using std::greater;
using std::vector;


class point { 
public: 
    point(double x, double y) : m_x(x), m_y(y) { } 
    double mag() const {return sqrt(m_x * m_x + m_y * m_y); } 
    double dist(const point& p) const {
        return sqrt(pow(m_x - p.m_x, 2)+ pow(m_y - p.m_y, 2)); 
    } 
private: 
   double m_x; 
   double m_y;
};
void test_bind2()
{
    vector<point> v;
    v.push_back(point(11, 11));
    v.push_back(point(10, 12));
    v.push_back(point(13, 14));
    const point k(10, 10);
    transform(v.begin(), v.end(),
              ostream_iterator<double>(cout, "\n"),
              bind(&point::dist, k, _1));
}

void test_bind1()
{
    vector<int> v;
    v.push_back(3);
    v.push_back(4);
    v.push_back(5);
    transform(v.begin(), v.end(),
              ostream_iterator<int>(cout, "\n"),
              bind(multiplies<int>(), _1, _1));
}
void test_bind3()
{
    int i = 10;
    function<int ()> fn = bind(multiplies<int>(), 3, i);
    assert(fn() == 30);
    i++;
    assert(fn() == 30);
}
void test_bind4()
{
    int i = 10;
    function<int ()> fn = bind(multiplies<int>(), 3, cref(i));
    assert(fn() == 30);
    i++;
    assert(fn() == 33);
}
void test_bind5()
{
    vector<point> v;
    v.push_back(point(3, 4));
    v.push_back(point(5, 12));
    v.push_back(point(8, 15));

    cout << count_if(v.begin(), v.end(),
                     bind(greater<double>(), bind(&point::mag, _1), 10)) << endl;
}



int main()
{
    test_bind1();
    test_bind2();
    test_bind3();
    test_bind4();
    test_bind5();
}

